﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace IR.Common.Utilities
{
    public static class HeartBeat
    {
        /// http://stackoverflow.com/questions/3689728/ping-a-hostname-on-the-network
        /// Created by Vinay B R
        /// <summary>
        /// Sees if host is reachable
        /// </summary>
        /// <param name="host">String of hostname</param>
        /// <returns>Empty if reachable, error if not</returns>
        public static string PingHost(string host)
        {
            //string to hold our return messge
            string returnMessage = string.Empty;

            //first make sure we actually have an internet connection
            if (HasConnection())
            {
                //IPAddress instance for holding the returned host
                IPAddress address = Dns.GetHostEntry(host).AddressList.First(); ;

                //set the ping options, TTL 128
                PingOptions pingOptions = new PingOptions(128, true);

                //create a new ping instance
                Ping ping = new Ping();

                //32 byte buffer (create empty)
                byte[] buffer = new byte[32];

                //here we will ping the host 4 times (standard)
                for (int i = 0; i < 4; i++)
                {
                    try
                    {
                        //send the ping 4 times to the host and record the returned data.
                        //The Send() method expects 4 items:
                        //1) The IPAddress we are pinging
                        //2) The timeout value
                        //3) A buffer (our byte array)
                        //4) PingOptions
                        PingReply pingReply = ping.Send(address, 1000, buffer, pingOptions);

                        //make sure we dont have a null reply
                        if (!(pingReply == null))
                        {
                            switch (pingReply.Status)
                            {
                                case IPStatus.Success:
                                    // We want the message empty instead of ping info
                                    //returnMessage = string.Format("Reply from {0}: bytes={1} time={2}ms TTL={3}", pingReply.Address, pingReply.Buffer.Length, pingReply.RoundtripTime, pingReply.Options.Ttl);
                                    break;
                                case IPStatus.TimedOut:
                                    returnMessage = "Connection has timed out...";
                                    break;
                                default:
                                    returnMessage = string.Format("Ping failed: {0}", pingReply.Status.ToString());
                                    break;
                            }
                        }
                        else
                            returnMessage = "Connection failed for an unknown reason...";
                    }
                    catch (PingException ex)
                    {
                        returnMessage = string.Format("Connection Error: {0}", ex.Message);
                    }
                    catch (SocketException ex)
                    {
                        returnMessage = string.Format("Connection Error: {0}", ex.Message);
                    }
                }
            }
            else
                returnMessage = "No Internet connection found...";

            //return the message
            return returnMessage;
        }

        /// http://stackoverflow.com/questions/2031824/what-is-the-best-way-to-check-for-internet-connectivity-using-net
        /// Created by ChaosPandion
        /// <summary>
        /// Checks for internet connection
        /// </summary>
        /// <returns>True if connected</returns>
        public static bool HasConnection()
        {
            try
            {
                using (var client = new WebClient())
                using (var stream = client.OpenRead("http://www.google.com"))
                {
                    return true;
                }
            }
            catch
            {
                return false;
            }
        }
    }
}
